<!DOCTYPE html>
<html>
	<head>
		<title>Miscellanea_6</title>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
		<link rel="stylesheet" type="text/css" href="../style/MainFrameCss.css" />
		<script src="../Js/MainFrameJs.js"></script>
	</head>
	<body onload="init();">
		<h1>篡改消息实现panel控件的拖动</h1>
		<p>篡改消息什么的最开心了！！</p>
		<p>咳咳咳，有时候呢，我们需要制作一个可以在Form里自由被拖动的panel，那么我们可以通过如下的方法来实现。</p>
		<p>先介绍下WM_NCHITTEST消息，在鼠标点击到panel上的时候，系统会向panel发出这个消息，用以询问鼠标究竟点在了它的什么地方，从而执行不同的命令。</p>
		<p>一般来说是点击在HTClient（客户区）上了，但是我们可以悄悄的改一下，骗系统说点在了HTCaption（标题区）上了。这样系统就会乖乖的把panel置为拖动状态，接下来就跟着鼠标动了。</p>
		<p>写了个小例子，它看起来是这样的。</p>
		<p>
			<img src="../images/MiscellaneaSourceCode2Image1.png" />
		</p>
		<p class="title">MiscellaneaSourceCode2/Unit1.pas</p>
		<div class="codes">
			<div class="lineNum">
				<pre></pre>
			</div>
			<textarea readonly="readonly" onScroll="lineNumDivScrollTo(this);">
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, OleCtrls, SHDocVw_EWB, EwbCore;

type
  TMyPanel = class(TPanel)
  private
    procedure WmNCHitTest(var Msg : TWMNCHitTest); message WM_NCHITTEST;
  end;

  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    MyPanel1: TMypanel;
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ MyPanel }

procedure TMyPanel.WmNCHitTest(var Msg: TWMNCHitTest);
var
  p: TPoint;
begin
  inherited;
  p := Point(Msg.XPos,Msg.YPos);
  p := ScreenToClient(p);
  if PtInRect(rect(0,0,Width, 50), p) then
  begin
    msg.Result := HTCaption;
  end;
end;

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
  MyPanel1 := TMypanel.Create(Self);
  MyPanel1.Parent := Self;
  MyPanel1.SetBounds(0,0,300,200);
  MyPanel1.Anchors := [akTop, akRight];
  MyPanel1.Caption := '来拖动我啊。';
  MyPanel1.BorderStyle := bsSingle;
  MyPanel1.BorderWidth := 10;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  MyPanel1.Free;
end;

end.
			</textarea>
		</div>
		<p>第10行，定义自己的panel类，从TPanel继承。<br/>
		第12行，截获WM_NCHITTEST消息。<br/>
		第41行，当鼠标点击在rect（0,0,panel.width,50）的范围内是，骗系统说是点在了标题栏上。（别和我说你看不懂rect）<br/>
		第51行，动态生成我们的panel。<br/>
		第62行，自己Create要自己Free。</p>
	</body>
</html>
